<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>vdom</title>
  </head>
  <body>
    <div id="container"></div>
    <button id="btn-change">change</button>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-class.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-props.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-style.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/snabbdom-eventlisteners.js"></script>
    <script src="https://cdn.bootcss.com/snabbdom/0.7.3/h.js"></script>
  </body>
</html>
<script>
  const h = window.snabbdom.h // 返回一个 vnode
  const container = document.getElementById('container') // 挂载 Vdom 的容器

  /**
   * sel 标签 ID class
   * data 属性 attr
   * children 子节点
   * elm vnode 对应 DOM 真实元素
   * key
   */
  let vnode = h(
    'ul#list', // 标签ul id=list
    {}, // attr 属性
    [
      h('li.item', {}, 'Item 1'), // 子节点
      h('li.item', {}, 'Item 2')
    ]
  )
  console.log(vnode)

  /**
   * snabbdom.init 返回一个patch 函数
   * 第一个参数不是 vnode、创建一个空vnode，关联DOM元素
   * 判断 newVnode oldVnode是否相等 （判断sel key）
   * 如果是相同的 vnode 然后进行对比
   * 细节：两个都有子元素children - 头和头比 结束和结束比 开始和结束对比 结束和开始对比
   * 如果是不同的vnode 删除 销重建
   */

  // 定义 patch
  const patch = snabbdom.init([
    snabbdom_class, // 提供了对元素类名操作的功能，包括添加、删除和切换类名
    snabbdom_props, // 用于处理元素的属性，包括属性的设置、获取和删除。
    snabbdom_style, // 用于处理元素的样式，包括样式的设置和获取。
    snabbdom_eventlisteners // 用于处理元素的事件监听器，包括添加和删除事件监听器，以及触发事件。
  ])
  patch(container, vnode) // 初次渲染：虚拟DOM渲染到HTML

  function render() {
    return h('ul#list', {}, [h('li.item', {}, 'Item 1'), h('li.item', {}, 'Item 3'), h('li.item', {}, 'Item 2')])
  }
  document.getElementById('btn-change').addEventListener('click', () => {
    const newVnode = render() // 新的虚拟的DOM
    patch(vnode, newVnode) // patch 旧的vnode 新的vnode
    vnode = newVnode // patch 之后，应该用新的覆盖现有的 vnode
  })
</script>
